import axios from 'axios';

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // api的base_url
  timeout: 5000 // 请求超时时间
});

// request拦截器
service.interceptors.request.use(
  config => {
    // 在发送请求之前做一些处理
    const token = localStorage.getItem('token');
    if (token) {
      config.headers['Authorization'] = 'Bearer ' + token;
    }
    return config;
  },
  error => {
    // 处理请求错误
    console.log(error); // for debug
    return Promise.reject(error);
  }
);

// response拦截器
service.interceptors.response.use(
  response => {
    // 在响应之前做一些处理
    const token = response.headers['authorization'];
    if (token) {
      localStorage.setItem('token', token);
    }
    return response.data;
  },
  error => {
    // 处理响应错误
    console.log(error); // for debug
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 无权限访问，需要刷新token
          return refreshToken(error);
        case 403:
          // 登录过期，需要重新登录
          return reLogin();
        default:
          // 其它错误
          return Promise.reject(error);
      }
    } else {
      // 网络错误
      return Promise.reject(error);
    }
  }
);

// 刷新token
let isRefreshing = false;
let requests = [];

function refreshToken(error) {
  if (!isRefreshing) {
    isRefreshing = true;
    // 发送刷新token的请求
    const token = localStorage.getItem('token');
    return axios.post('/api/refresh_token', { token: token }).then(response => {
      localStorage.setItem('token', response.data.token);
      // 刷新token成功，重新发送请求
      error.config.headers['Authorization'] = 'Bearer ' + response.data.token;
      requests.forEach(cb => cb(response.data.token));
      requests = [];
      return axios(error.config);
    }).catch(() => {
      // 刷新token失败，需要重新登录
      return reLogin();
    }).finally(() => {
      isRefreshing = false;
    });
  } else {
    // 正在刷新token，将请求存储到队列中
    return new Promise((resolve) => {
      requests.push((token) => {
        error.config.headers['Authorization'] = 'Bearer ' + token;
        resolve(axios(error.config));
      });
    });
  }
}

// 重新登录
function reLogin() {
  // 清除token等用户信息
  localStorage.removeItem('token');
  // 跳转到登录页面
  window.location.href = '/login';
}

export default service;

// 在上面的代码中，我们使用了axios的拦截器来实现无痛刷新token的处理。当服务端返回401错误时，表示当前用户的token无效，需要刷新token。我们通过一个变量isRefreshing来记录是否正在刷新token，如果正在刷新token，我们将请求存储到队列中，等待刷新成功后再发送。如果刷新token失败，我们需要重新登录。当服务端返回403错误时，表示用户登录已经过期，需要重新登录。

// 在发送请求时，我们会从localStorage中获取token并设置到请求头中，服务端返回响应时，我们会从响应
